package com.gitee.jmash.oidc.client.web.controller;

import java.io.IOException;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.LogFactory;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.eclipse.microprofile.jwt.JsonWebToken;
import com.gitee.jmash.common.event.SafeEvent;
import com.gitee.jmash.oidc.client.oauth.OidcClient;
import com.gitee.jmash.oidc.client.oauth.models.AuthCodeTokenResp;
import com.gitee.jmash.oidc.client.oauth.models.UserInfoResp;
import com.gitee.jmash.oidc.client.web.OauthUtil;
import com.gitee.jmash.oidc.client.web.models.RedirectResult;
import com.gitee.jmash.rbac.client.shiro.authc.JmashShiroJwtToken;
import jakarta.enterprise.context.RequestScoped;
import jakarta.enterprise.event.Event;
import jakarta.inject.Inject;
import jakarta.mvc.Controller;
import jakarta.mvc.MvcContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.core.Context;

/** Default View. */
@Path("/authcode")
@Controller
@RequestScoped
public class AuthCodeController {

  @Inject
  private MvcContext mvc;
  /** Base Redirect @RedirectScoped. */
  @Inject
  private RedirectResult redirectResult;
  /** 安全日志. */
  @Inject
  Event<SafeEvent> event;
  @Inject
  OidcClient oidcClient;

  @GET
  public String execute(@Context HttpServletRequest req, @Context HttpServletResponse resp)
      throws IOException {
    String state = req.getParameter("state");
    if (!req.getSession().getAttribute(OauthUtil.OIDC_STATE).equals(state)) {
      LogFactory.getLog(AuthCodeController.class).error("state 不一致");
      return null;
    }
    String code = req.getParameter("code");
    String idToken = req.getParameter("id_token");

    if (StringUtils.isNotBlank(code)) {
      AuthCodeTokenResp token = oidcClient.authCodeToken(code);
      System.out.println(token);
      // 获取用户信息
      UserInfoResp userInfo = oidcClient.userInfo(token.getAccessToken());
      System.out.println(userInfo.toString());
      idToken = token.getIdToken();
    }
    Subject subject = SecurityUtils.getSubject();
    JmashShiroJwtToken jwtToken = new JmashShiroJwtToken(idToken);
    try {
      subject.login(jwtToken);
    } catch (Exception ex) {
      redirectResult.addError("login.error", "");
      resp.sendRedirect(mvc.uri("AuthLoginController#execute").toString());
      return null;
    }
    JsonWebToken webToken = (JsonWebToken) subject.getPrincipal();
    event.fireAsync(SafeEvent.login(webToken.getSubject(), "", true));
    return loginSuccess("", req, resp);
  }

  /** Login Success Redirect. */
  public String loginSuccess(String backurl, HttpServletRequest req, HttpServletResponse resp)
      throws IOException {
    SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(req);
    // Redirect backurl.
    if (StringUtils.isNotBlank(backurl)) {
      resp.sendRedirect(backurl);
      return null;
    } else if (savedRequest != null
        && savedRequest.getMethod().equalsIgnoreCase(AccessControlFilter.GET_METHOD)) {
      resp.sendRedirect(savedRequest.getRequestUrl());
      return null;
    } else {
      resp.sendRedirect(mvc.uri("DefaultController#execute").toString());
      return null;
    }
  }

}
